-------------------------------------------------------------------------------
-- Archivo: 			 vector_register_file.vhdl
-- Fecha de creación:            20/01/2011
-- Ultima fecha de modificación: 15/02/2011
-- Diseñador: 			 Jesús Pérez
-- Diseño: 			 vector_register_file
-- Propósito: 			 Archivo de registros vectorial para el 
-- 				 microprocesador vectorial
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;

entity vector_register_file is
    port(
        CLK_i          : in  std_logic;
        WRITE_ENABLE_i : in  std_logic;
        DATA_i         : in  std_logic_vector  (3 downto 0);
        RA_i           : in  std_logic_vector  (1 downto 0);
        RB_i           : in  std_logic_vector  (1 downto 0);
        RD_i           : in  std_logic_vector  (1 downto 0);
        CA_i           : in  std_logic_vector  (1 downto 0);
        CB_i           : in  std_logic_vector  (1 downto 0);
        CD_i           : in  std_logic_vector  (1 downto 0);
        READ_DATA1_o   : out std_logic_vector  (3 downto 0);
        READ_DATA2_o   : out std_logic_vector  (3 downto 0)
    );
end vector_register_file;

architecture structural of vector_register_file is

component vector
    port(
        CLK_i 		: in  std_logic;
    	WRITE_ENABLE0_i : in  std_logic;
    	WRITE_ENABLE1_i : in  std_logic;
    	WRITE_ENABLE2_i : in  std_logic;
    	WRITE_ENABLE3_i : in  std_logic;
    	DATA_i          : in  std_logic_vector (3 downto 0);
    	DATA0_o 	: out std_logic_vector (3 downto 0);
    	DATA1_o 	: out std_logic_vector (3 downto 0);
    	DATA2_o 	: out std_logic_vector (3 downto 0);
    	DATA3_o 	: out std_logic_vector (3 downto 0)
    );
end component;

component decoder
    port ( 
        SEL    : in  std_logic_vector (1 downto 0);
        outlet : out std_logic_vector (3 downto 0)
    );
end component;
	
component mux
    port (
        a : in  std_logic_vector (3 downto 0);
	b : in  std_logic_vector (3 downto 0);
	c : in  std_logic_vector (3 downto 0);
	d : in  std_logic_vector (3 downto 0); 
    	s : in  std_logic_vector (1 downto 0); 
    	o : out std_logic_vector (3 downto 0)
  	); 
end component;

component and_gate
    port(
        A : in  std_logic;
        B : in  std_logic;
        C : in  std_logic;
        O : out std_logic
    );
end component;

component not_gate
    port(
	A_i : in  std_logic;
	B_o : out std_logic
    );
end component;

    signal clk_wire		: std_logic;
    signal write_enable0_wire0  : std_logic;
    signal write_enable1_wire0  : std_logic;
    signal write_enable2_wire0  : std_logic;
    signal write_enable3_wire0  : std_logic;
    signal write_enable0_wire1  : std_logic;
    signal write_enable1_wire1  : std_logic;
    signal write_enable2_wire1  : std_logic;
    signal write_enable3_wire1  : std_logic;
    signal write_enable0_wire2  : std_logic;
    signal write_enable1_wire2  : std_logic;
    signal write_enable2_wire2  : std_logic;
    signal write_enable3_wire2  : std_logic;
    signal write_enable0_wire3  : std_logic;
    signal write_enable1_wire3  : std_logic;
    signal write_enable2_wire3  : std_logic;
    signal write_enable3_wire3  : std_logic;
    signal data_out0_wire0      : std_logic_vector(3 downto 0);
    signal data_out1_wire0 	: std_logic_vector(3 downto 0);
    signal data_out2_wire0 	: std_logic_vector(3 downto 0);
    signal data_out3_wire0 	: std_logic_vector(3 downto 0);
    signal data_out0_wire1 	: std_logic_vector(3 downto 0);
    signal data_out1_wire1 	: std_logic_vector(3 downto 0);
    signal data_out2_wire1 	: std_logic_vector(3 downto 0);
    signal data_out3_wire1 	: std_logic_vector(3 downto 0);
    signal data_out0_wire2 	: std_logic_vector(3 downto 0);
    signal data_out1_wire2 	: std_logic_vector(3 downto 0);
    signal data_out2_wire2 	: std_logic_vector(3 downto 0);
    signal data_out3_wire2 	: std_logic_vector(3 downto 0);
    signal data_out0_wire3 	: std_logic_vector(3 downto 0);
    signal data_out1_wire3 	: std_logic_vector(3 downto 0);
    signal data_out2_wire3 	: std_logic_vector(3 downto 0);
    signal data_out3_wire3 	: std_logic_vector(3 downto 0);
    signal mux_ca0_wire    	: std_logic_vector(3 downto 0);
    signal mux_ca1_wire    	: std_logic_vector(3 downto 0);
    signal mux_ca2_wire    	: std_logic_vector(3 downto 0);
    signal mux_ca3_wire    	: std_logic_vector(3 downto 0);
    signal mux_cb0_wire    	: std_logic_vector(3 downto 0);
    signal mux_cb1_wire    	: std_logic_vector(3 downto 0);
    signal mux_cb2_wire    	: std_logic_vector(3 downto 0);
    signal mux_cb3_wire    	: std_logic_vector(3 downto 0);
    signal outlet_wire     	: std_logic_vector(3 downto 0);
    signal outlet_wire0    	: std_logic_vector(3 downto 0);
    signal outlet_wire1    	: std_logic_vector(3 downto 0);
    signal outlet_wire2    	: std_logic_vector(3 downto 0);
    signal outlet_wire3   	: std_logic_vector(3 downto 0);
    
begin

    NOT0 : not_gate port map(
	A_i => CLK_i,
	B_o => clk_wire
    );

    VECTOR0 : vector port map(
    	CLK_i           => clk_wire,
    	WRITE_ENABLE0_i => write_enable0_wire0,
    	WRITE_ENABLE1_i => write_enable1_wire0,
    	WRITE_ENABLE2_i => write_enable2_wire0,
    	WRITE_ENABLE3_i => write_enable3_wire0,
    	DATA_i          => DATA_i,
    	DATA0_o         => data_out0_wire0,
    	DATA1_o         => data_out1_wire0,
    	DATA2_o         => data_out2_wire0,
    	DATA3_o         => data_out3_wire0
    );

    VECTOR1 : vector port map(
    	CLK_i           => clk_wire,
    	WRITE_ENABLE0_i => write_enable0_wire1,
    	WRITE_ENABLE1_i => write_enable1_wire1,
    	WRITE_ENABLE2_i => write_enable2_wire1,
    	WRITE_ENABLE3_i => write_enable3_wire1,
    	DATA_i          => DATA_i,
    	DATA0_o         => data_out0_wire1,
    	DATA1_o         => data_out1_wire1,
    	DATA2_o         => data_out2_wire1,
    	DATA3_o         => data_out3_wire1
    );

    VECTOR2 : vector port map(
    	CLK_i           => clk_wire,
    	WRITE_ENABLE0_i => write_enable0_wire2,
    	WRITE_ENABLE1_i => write_enable1_wire2,
    	WRITE_ENABLE2_i => write_enable2_wire2,
    	WRITE_ENABLE3_i => write_enable3_wire2,
    	DATA_i          => DATA_i,
    	DATA0_o         => data_out0_wire2,
    	DATA1_o         => data_out1_wire2,
    	DATA2_o         => data_out2_wire2,
    	DATA3_o         => data_out3_wire2
    );

    VECTOR3 : vector port map(
    	CLK_i 		=> clk_wire,
    	WRITE_ENABLE0_i => write_enable0_wire3,
    	WRITE_ENABLE1_i => write_enable1_wire3,
    	WRITE_ENABLE2_i => write_enable2_wire3,
    	WRITE_ENABLE3_i => write_enable3_wire3,
    	DATA_i 	        => DATA_i,
    	DATA0_o         => data_out0_wire3,
    	DATA1_o 	=> data_out1_wire3,
    	DATA2_o 	=> data_out2_wire3,
    	DATA3_o         => data_out3_wire3
    );

    DEC : decoder port map ( 
    	SEL    => RD_i,
    	outlet => outlet_wire 
    );

    DEC0 : decoder port map ( 
    	SEL    => CD_i,
    	outlet => outlet_wire0
    );

    DEC1 : decoder port map ( 
    	SEL    => CD_i,
    	outlet => outlet_wire1
    );

    DEC2 : decoder port map ( 
    	SEL    => CD_i,
    	outlet => outlet_wire2 
    );

    DEC3 : decoder port map ( 
    	SEL    => CD_i,
    	outlet => outlet_wire3
    );

    AND0 : and_gate port map(
    	A => WRITE_ENABLE_i,
    	B => outlet_wire0(0),
    	C => outlet_wire(0),
    	O => write_enable0_wire0
    );
 
    AND1 : and_gate port map(
    	A => WRITE_ENABLE_i,
    	B => outlet_wire0(1),
    	C => outlet_wire(0),
    	O => write_enable1_wire0
    );

    AND2 : and_gate port map(
    	A => WRITE_ENABLE_i,
    	B => outlet_wire0(2),
    	C => outlet_wire(0),
    	O => write_enable2_wire0
    );	

    AND3 : and_gate port map(
    	A => WRITE_ENABLE_i,
    	B => outlet_wire0(3),
    	C => outlet_wire(0),
    	O => write_enable3_wire0
    );

    AND4 : and_gate port map(
    	A => WRITE_ENABLE_i,
    	B => outlet_wire1(0),
    	C => outlet_wire(1),
    	O => write_enable0_wire1
    );	
 
    AND5 : and_gate port map(
    	A => WRITE_ENABLE_i,
    	B => outlet_wire1(1),
    	C => outlet_wire(1),
    	O => write_enable1_wire1
    );	

    AND6 : and_gate port map(
    	A => WRITE_ENABLE_i,
    	B => outlet_wire1(2),
    	C => outlet_wire(1),
    	O => write_enable2_wire1
    );

    AND7 : and_gate port map(
    	A => WRITE_ENABLE_i,
    	B => outlet_wire1(3),
    	C => outlet_wire(1),
    	O => write_enable3_wire1
    );	

    AND8 : and_gate port map(
    	A => WRITE_ENABLE_i,
    	B => outlet_wire2(0),
    	C => outlet_wire(2),
    	O => write_enable0_wire2
    );	
 
    AND9 : and_gate port map(
    	A => WRITE_ENABLE_i,
    	B => outlet_wire2(1),
    	C => outlet_wire(2),
    	O => write_enable1_wire2
    );	

    AND10 : and_gate port map(
    	A => WRITE_ENABLE_i,
    	B => outlet_wire2(2),
    	C => outlet_wire(2),
    	O => write_enable2_wire2
    );	

    AND11 : and_gate port map(
    	A => WRITE_ENABLE_i,
    	B => outlet_wire2(3),
    	C => outlet_wire(2),
    	O => write_enable3_wire2
    );	

    AND12 : and_gate port map(
    	A => WRITE_ENABLE_i,
    	B => outlet_wire3(0),
    	C => outlet_wire(3),
    	O => write_enable0_wire3
  	);
 
    AND13 : and_gate port map(
    	A => WRITE_ENABLE_i,
    	B => outlet_wire3(1),
    	C => outlet_wire(3),
    	O => write_enable1_wire3
    );

    AND14 : and_gate port map(
    	A => WRITE_ENABLE_i,
    	B => outlet_wire3(2),
    	C => outlet_wire(3),
    	O => write_enable2_wire3
    );

    AND15 : and_gate port map(
    	A => WRITE_ENABLE_i,
    	B => outlet_wire3(3),
    	C => outlet_wire(3),
    	O => write_enable3_wire3
    );

    MUX_CA0 : mux port map (
   	a => data_out0_wire0,
    	b => data_out1_wire0,
    	c => data_out2_wire0,
    	d => data_out3_wire0,
    	s => CA_i, 
    	o => mux_ca0_wire
    ); 

    MUX_CA1 : mux port map (
    	a => data_out0_wire1,
    	b => data_out1_wire1,
    	c => data_out2_wire1,
    	d => data_out3_wire1,
    	s => CA_i, 
    	o => mux_ca1_wire
    );

    MUX_CA2 : mux port map (
    	a => data_out0_wire2,
    	b => data_out1_wire2,
    	c => data_out2_wire2,
    	d => data_out3_wire2,
    	s => CA_i, 
    	o => mux_ca2_wire
    );

    MUX_CA3 : mux port map (
    	a => data_out0_wire3,
    	b => data_out1_wire3,
    	c => data_out2_wire3,
    	d => data_out3_wire3,
    	s => CA_i, 
    	o => mux_ca3_wire 
    );

    MUX_CB0 : mux port map (
    	a => data_out0_wire0,
    	b => data_out1_wire0,
    	c => data_out2_wire0,
    	d => data_out3_wire0,
    	s => CB_i, 
    	o => mux_cb0_wire
    ); 

    MUX_CB1 : mux port map (
    	a => data_out0_wire1,
    	b => data_out1_wire1,
    	c => data_out2_wire1,
    	d => data_out3_wire1,
    	s => CB_i, 
    	o => mux_cb1_wire
    );

    MUX_CB2 : mux port map (
    	a => data_out0_wire2,
    	b => data_out1_wire2,
    	c => data_out2_wire2,
    	d => data_out3_wire2,
    	s => CB_i, 
    	o => mux_cb2_wire
    ); 

    MUX_CB3 : mux port map (
    	a => data_out0_wire3,
    	b => data_out1_wire3,
    	c => data_out2_wire3,
    	d => data_out3_wire3,
    	s => CB_i, 
    	o => mux_cb3_wire
    );

    MUX_RA : mux port map (
    	a => mux_ca0_wire,
    	b => mux_ca1_wire,
    	c => mux_ca2_wire,
    	d => mux_ca3_wire,
    	s => RA_i, 
    	o => READ_DATA1_o
    );

    MUX_RB : mux port map (
    	a => mux_cb0_wire,
    	b => mux_cb1_wire,
    	c => mux_cb2_wire,
    	d => mux_cb3_wire,
    	s => RB_i, 
    	o => READ_DATA2_o
    );

end structural;

